import { ref } from 'vue';

/**
 * 防抖钩子函数
 * @param fn 需要防抖的函数
 * @param delay 延迟时间，单位毫秒
 * @param immediate 是否立即执行
 */
export default function useDebounce<T extends (...args: any[]) => any>(
  fn: T,
  delay: number = 300,
  immediate: boolean = false
) {
  // 定时器
  const timer = ref<number | null>(null);
  
  // 是否可以执行
  const isReady = ref(immediate);
  
  // 是否正在执行
  const isRunning = ref(false);
  
  // 防抖函数
  const debounced = ((...args: Parameters<T>): Promise<ReturnType<T>> => {
    return new Promise((resolve, reject) => {
      // 如果正在执行，则直接返回
      if (isRunning.value) {
        return;
      }
      
      // 如果是立即执行，并且可以执行
      if (immediate && isReady.value) {
        isReady.value = false;
        isRunning.value = true;
        
        try {
          const result = fn(...args);
          isRunning.value = false;
          resolve(result);
        } catch (err) {
          isRunning.value = false;
          reject(err);
        }
        
        // 延迟后重置状态
        if (timer.value) {
          clearTimeout(timer.value);
        }
        
        timer.value = setTimeout(() => {
          isReady.value = true;
        }, delay) as unknown as number;
        
        return;
      }
      
      // 如果不是立即执行，则延迟执行
      if (timer.value) {
        clearTimeout(timer.value);
      }
      
      timer.value = setTimeout(() => {
        isRunning.value = true;
        
        try {
          const result = fn(...args);
          isRunning.value = false;
          resolve(result);
        } catch (err) {
          isRunning.value = false;
          reject(err);
        }
        
        if (immediate) {
          isReady.value = true;
        }
      }, delay) as unknown as number;
    });
  }) as (...args: Parameters<T>) => Promise<ReturnType<T>>;
  
  // 取消防抖
  const cancel = () => {
    if (timer.value) {
      clearTimeout(timer.value);
      timer.value = null;
    }
    
    isReady.value = immediate;
    isRunning.value = false;
  };
  
  return {
    debounced,
    isRunning,
    cancel
  };
} 